﻿using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using SqlTdd.Core.Model.Data;
using SqlTdd.Core.Properties;

namespace SqlTdd.Core.Model
{
    public interface ITestFactory
    {
        string ConnectionString();
        List<SqlTddTestSchema> GetTestCatalog();
        SqlTddTestSuite GetTestSuite(string schema, string suite);
        SqlTddTestSchema GetTestSchema(string schema);
    }

    public class TestFactory : ITestFactory
    {
        private readonly SqlTddDataContext _context;

        public TestFactory(SqlTddDataContext context)
        {
            _context = context;
        }

        public TestFactory()
        {
            _context = new SqlTddDataContext(ConnectionString());
        }

        #region ITestFactory Members

        public string ConnectionString()
        {
            var configConnectionString =
                ConfigurationManager.ConnectionStrings["SqlTdd.Core.Properties.Settings.ConnectionString"];
            if (configConnectionString != null)
                return configConnectionString.ToString();
            else
                return Settings.Default.ConnectionString;
        }

        public virtual List<SqlTddTestSchema> GetTestCatalog()
        {
            List<TestCatalog> catalog = (from cat in _context.TestCatalogs
                                              select cat).ToList();

            return CreateTestCatalog(catalog);
        }

        public virtual SqlTddTestSuite GetTestSuite(string schema, string suite)
        {
            List<TestCatalog> suiteMethods = (from cat in _context.TestCatalogs
                                              where cat.TestSchema == schema && cat.TestSuite == suite
                                              select cat).ToList();

            return CreateTestSuite(schema, suite, suiteMethods);
        }

        public virtual SqlTddTestSchema GetTestSchema(string schema)
        {
            List<TestCatalog> schemaMethods = (from cat in _context.TestCatalogs
                                               where cat.TestSchema == schema
                                               select cat).ToList();
            return CreateTestSchema(schema, schemaMethods);
        }

        #endregion
        private List<SqlTddTestSchema> CreateTestCatalog(List<TestCatalog> tests)
        {
            var schemas = new List<SqlTddTestSchema>();
            var schemaNames = (from test in tests
                           select test.TestSchema).Distinct();

            foreach (var schema in schemaNames)
            {
                schemas.Add(GetTestSchema(schema));
            }

            return schemas;
        }

        private SqlTddTestSuite CreateTestSuite(string schema, string suite, List<TestCatalog> tests)
        {
            var testSuite = new SqlTddTestSuite(schema, suite);

            foreach (var test in tests)
            {
                testSuite.AddTestMethod(new SqlTddTestMethod
                                      {
                                          Id = test.object_id,
                                          Name = test.TestMethod,
                                          TestSchema = test.TestSchema,
                                          TestSuite = test.TestSuite
                                      });
            }

            return testSuite;
        }

        private SqlTddTestSchema CreateTestSchema(string schema, List<TestCatalog> tests)
        {
            var testSchema = new SqlTddTestSchema(schema);

            var suites = (from catalog in tests
                                               where catalog.TestSchema == schema
                                               select catalog.TestSuite).Distinct();

            foreach (string suite in suites)
            {
                testSchema.AddSuite(GetTestSuite(schema, suite));
            }

            return testSchema;
        }
    }
}